﻿using System;
using System.Collections.Generic;

namespace RiskCalc.Modelo
{
    public class Carteira
    {
        // Ações da carteira
        public List<Acao> vetAcao;

        public double[,] matrizCorrelacao;
        public double[,] matrizCovariancia;
        public double varParametrico;
        public int janelaDias;
        public int confianca;
        public double confiancaPadrao;
        public double valorAcaoIbovespa;

        #region Singleton

        private static Carteira instancia;

        public static Carteira getInstance()
        {
            if (instancia == null)
            {
                instancia = new Carteira();
            }
            return instancia;
        }

        protected Carteira()
        {
            this.vetAcao = new List<Acao>();
        }

        #endregion

        public void calcularVarParametrico(int confianca, int janelaDias, int valorAcaoIbovespa)
        {
            this.confianca = confianca;
            this.janelaDias = janelaDias;
            this.valorAcaoIbovespa = valorAcaoIbovespa;

            confiancaPadrao = Calculos.inversaDistNormal(((Double)confianca) / 100);

            // Monta matriz de uma linha (vetor) de VaRs de cada ação
            double[,] vetVars = new double[1,vetAcao.Count];

            for(int i=0 ; i< vetAcao.Count ; i++)
            {
                vetAcao[i].calcularRetornosGeometricos();

                vetAcao[i].calcularMedia();

                vetAcao[i].calcularDesvioPadrao();

                vetAcao[i].calcularPosicao();

                vetAcao[i].calcularVarParametrico(confiancaPadrao);

                vetVars[0,i] = vetAcao[i].VarParametrico;
            }

            this.calcularMatrizCorrelacao();

            this.varParametrico = Calculos.varParametricoCarteira(vetVars, this.matrizCorrelacao);
        }

        public void calcularMatrizCorrelacao()
        {
            this.matrizCovariancia = new double[vetAcao.Count, vetAcao.Count];
            this.matrizCorrelacao = new double[vetAcao.Count, vetAcao.Count];

            for (int i = 0; i < vetAcao.Count; i++)
            {
                for (int j = 0; j < vetAcao.Count; j++)
                {
                    this.matrizCovariancia[i, j] = Calculos.covariancia(
                        this.vetAcao[i].VetDados.ConvertAll(new Converter<Dado, double>(Dado.DadoParaRetornoGeometrico)),
                        this.vetAcao[i].Media,
                        this.vetAcao[j].VetDados.ConvertAll(new Converter<Dado, double>(Dado.DadoParaRetornoGeometrico)),
                        this.vetAcao[j].Media);

                    this.matrizCorrelacao[i,j] = Calculos.correlacao(this.matrizCovariancia[i,j],
                                                this.vetAcao[i].DesvioPadrao,
                                                this.vetAcao[j].DesvioPadrao);
                }
            }
        }

        public bool carregarDados(int janelaDias, out string msgRetorno)
        {
            return Persistencia.Persistencia.carregarDadosDoBanco(this, out msgRetorno, janelaDias);
        }

        public bool gravarDados(out string msgRetorno)
        {
            return Persistencia.Persistencia.imprimirNoExcel(this, out msgRetorno, true);
        }
    }
}
